﻿using Module.FlowChart.Model;
using System;
using System.Drawing;
using System.Windows.Forms;

namespace Module.FlowChart.RunAble.View
{
    class NodePropertyEditorManager
    {
        static Size Rect = new Size(19200, 10800);
        static NodePropertyEditorManager Instance = new NodePropertyEditorManager();

        Form_NodePropertyEditor view;
        FCNode node;
        Action<FCNode, string> changed;

        public NodePropertyEditorManager()
        {
            view = new Form_NodePropertyEditor();

            view.Tab_Asg_LeftExp.SetOnTextEdited((s, e) =>
            {
                if (view.Tab_Asg_LeftExp.Text != node.LeftExp)
                {
                    node.LeftExp = view.Tab_Asg_LeftExp.Text;
                    changed?.Invoke(Instance.node, "");
                }
            });

            view.Tab_Asg_RightExp.SetOnTextEdited((s, e) =>
            {
                if (view.Tab_Asg_RightExp.Text != node.RightExp)
                {
                    node.RightExp = view.Tab_Asg_RightExp.Text;
                    changed?.Invoke(Instance.node, "");
                }
            });

            view.Tab_IF_ConditionBox.SetOnTextEdited((s, e) =>
            {
                if (view.Tab_IF_ConditionBox.Text != node.ConditionExp)
                {
                    node.ConditionExp = view.Tab_IF_ConditionBox.Text;
                    changed?.Invoke(Instance.node, "");
                }
            });

            view.Tab_IO_Exp.SetOnTextEdited((s, e) =>
            {
                if (view.Tab_IO_Exp.Text != node.IOExp)
                {
                    node.IOExp = view.Tab_IO_Exp.Text;
                    changed?.Invoke(Instance.node, "");
                }
            });

            view.IsInputChanged = () =>
            {
                if (view.IsInput == node.IsOutPut)
                {
                    node.IsOutPut = !view.IsInput;
                    changed?.Invoke(Instance.node, "");
                }
            };

            view.Tab_Terminal_ReturnExpOrPars.SetOnTextEdited((s, e) =>
            {
                if (node.IsStartNode)
                {
                    if (view.Tab_Terminal_ReturnExpOrPars.Text != node.Params)
                    {
                        node.Params = view.Tab_Terminal_ReturnExpOrPars.Text;
                        changed?.Invoke(Instance.node, "");
                    }
                }
                else
                {
                    if (view.Tab_Terminal_ReturnExpOrPars.Text != node.ReturnExp)
                    {
                        node.ReturnExp = view.Tab_Terminal_ReturnExpOrPars.Text;
                        changed?.Invoke(Instance.node, "");
                    }
                }
            });

            view.Tab_Common_Text1.SetOnTextEdited((s, e) =>
            {
                string t = (s as TextBox).Text;
                int v;
                if (!int.TryParse(t, out v) || v < 0 || v > Rect.Width)
                {
                    (s as TextBox).Text = "0";
                    return;
                }
                if (Instance.node.LogicRect.Width + v > Rect.Width)
                {
                    v = Math.Max(Rect.Width - Instance.node.LogicRect.Width, 0);
                    (s as TextBox).Text = "" + v;
                }
                if (Instance.node.LogicRect.X == v)
                {

                    return;
                }

                Instance.node.LogicRect.X = int.Parse((s as TextBox).Text);
                Instance.changed?.Invoke(Instance.node, "rect");
            });
            view.Tab_Common_Text2.SetOnTextEdited((s, e) =>
            {
                string t = (s as TextBox).Text;
                int v;
                if (!int.TryParse(t, out v) || v < 0 || v > Rect.Height)
                {
                    (s as TextBox).Text = "0";
                    return;
                }
                if (Instance.node.LogicRect.Height + v > Rect.Height)
                {
                    v = Math.Max(Rect.Width - Instance.node.LogicRect.Height, 0);
                    (s as TextBox).Text = "" + v;
                }
                if (Instance.node.LogicRect.Y == v)
                    return;
                Instance.node.LogicRect.Y = int.Parse((s as TextBox).Text);
                Instance.changed?.Invoke(Instance.node, "rect");
            });
            view.Tab_Common_Text3.SetOnTextEdited((s, e) =>
            {
                string t = (s as TextBox).Text;
                int v;
                if (!int.TryParse(t, out v) || v < 10)
                {
                    (s as TextBox).Text = "10";
                    return;
                }
                if (Instance.node.LogicRect.X + v > Rect.Width)
                {
                    v = Math.Max(Rect.Width - Instance.node.LogicRect.X, 10);
                    (s as TextBox).Text = "" + v;
                }
                if (Instance.node.LogicRect.Width == v)
                    return;
                Instance.node.LogicRect.Width = int.Parse((s as TextBox).Text);
                Instance.changed?.Invoke(Instance.node, "rect");
            });
            view.Tab_Common_Text4.SetOnTextEdited((s, e) =>
            {
                string t = (s as TextBox).Text;
                int v;
                if (!int.TryParse(t, out v) || v < 10)
                {
                    (s as TextBox).Text = "10";
                    return;
                }
                if (Instance.node.LogicRect.Y + v > Rect.Height)
                {
                    v = Math.Max(Rect.Height - Instance.node.LogicRect.Y, 10);
                    (s as TextBox).Text = "" + v;
                }
                if (Instance.node.LogicRect.Height == v)
                    return;
                Instance.node.LogicRect.Height = int.Parse((s as TextBox).Text);
                Instance.changed?.Invoke(Instance.node, "rect");
            });



            //字体选择
            view.Tab_Common_Label7.Click += (s, e) =>
            {
                FontDialog ff = new FontDialog();
                if (ff.ShowDialog() == DialogResult.OK)
                {
                    Font f = ff.Font;
                    node.Font = f;
                    RefreshFontAndColor();
                    changed?.Invoke(node, "Font");

                }
            };
            //背景颜色
            view.Tab_Common_Label_BackColor.Click += (s, e) =>
            {
                ColorDialog cd = new ColorDialog();
                if (cd.ShowDialog() == DialogResult.OK)
                {
                    Color c = cd.Color;
                    node.BackGroundColor = c;
                    RefreshFontAndColor();
                    changed?.Invoke(node, "Color");
                }
            };
        }


        static public void Show(FCNode node, Action<FCNode, string> changed, Action<Form> call = null)
        {
            Instance.view.TabPagesMain.SuspendLayout();
            if (node == null)
            {

                SetPagesVisible(FCNodeType.Non);
                Instance.node = null;
                Instance.changed = null;
                if (call != null)
                {
                    call.Invoke(Instance.view);
                }
            }
            else
            {

                SetPagesVisible(node.Type);
                Instance.node = node;
                Instance.changed = changed;
                SetPageState();
                RefreshPosition();
                RefreshFontAndColor();
                //Instance.view.RefreshSize();
                //Instance.view.Visible = true;
                if (call == null)
                {
                    Instance.view.Show();
                }
                else
                {
                    call(Instance.view);
                }

            }
            Instance.view.TabPagesMain.ResumeLayout();
        }

        static void RefreshFontAndColor()
        {
            Instance.view.Tab_Common_Label7.Text = "字体:" + Instance.node.Font.FontFamily.Name;
            Instance.view.Tab_Common_Label_BackColor.BackColor = Instance.node.BackGroundColor;
        }

        static public void RefreshPosition()
        {
            Instance.view.Tab_Common_Label1.Text = "ID:" + Instance.node.Id;
            Instance.view.Tab_Common_Text1.Text = "" + Instance.node.LogicRect.X;
            Instance.view.Tab_Common_Text2.Text = "" + Instance.node.LogicRect.Y;
            Instance.view.Tab_Common_Text3.Text = "" + Instance.node.LogicRect.Width;
            Instance.view.Tab_Common_Text4.Text = "" + Instance.node.LogicRect.Height;
        }
        static public void Hide()
        {
            Instance.view.Visible = false;
        }
        static void SetPagesVisible(FCNodeType nothide)
        {
            if (nothide == FCNodeType.Non)
            {
                foreach (TabPage pg in Instance.view.TabPagesMain.TabPages)
                {
                    pg.Parent = null;
                }
                return;
            }

            foreach (TabPage pg in Instance.view.TabPagesMain.TabPages)
            {
                if (pg != Instance.view.Tab_Common)
                    pg.Parent = null;
            }
            switch (nothide)
            {
                case FCNodeType.Non:
                    break;
                case FCNodeType.Terminal:
                    Instance.view.Tab_Common.Parent = Instance.view.TabPagesMain;
                    Instance.view.Tab_Terminal.Parent = Instance.view.TabPagesMain;
                    break;
                case FCNodeType.Assign:
                    Instance.view.Tab_Common.Parent = Instance.view.TabPagesMain;
                    Instance.view.Tab_Asg.Parent = Instance.view.TabPagesMain;
                    break;
                case FCNodeType.IF:
                    Instance.view.Tab_Common.Parent = Instance.view.TabPagesMain;
                    Instance.view.Tab_IF.Parent = Instance.view.TabPagesMain;
                    break;
                case FCNodeType.IO:
                    Instance.view.Tab_Common.Parent = Instance.view.TabPagesMain;
                    Instance.view.Tab_IO.Parent = Instance.view.TabPagesMain;
                    break;
                case FCNodeType.Label:
                    Instance.view.Tab_Common.Parent = Instance.view.TabPagesMain;
                    Instance.view.Tab_Label.Parent = Instance.view.TabPagesMain;
                    break;
                default:
                    break;
            }
        }
        static void SetPageState()
        {
            var node = Instance.node;
            if (node == null)
                return;
            switch (node.Type)
            {
                case FCNodeType.Non:
                    return;
                case FCNodeType.Terminal:
                    if (node.IsStartNode)
                    {
                        Instance.view.Tab_Terminal_TipLabel.Text = "请输入参数\n例如\n\ta,b,c";
                        Instance.view.Tab_Terminal_Label1.Text = "参数";
                        Instance.view.Tab_Terminal_ReturnExpOrPars.Text = node.Params;
                    }
                    else
                    {
                        Instance.view.Tab_Terminal_TipLabel.Text = "请输入返回值\n例如\n\ta+1";
                        Instance.view.Tab_Terminal_Label1.Text = "表达式";
                        Instance.view.Tab_Terminal_ReturnExpOrPars.Text = node.ReturnExp;
                    }
                    break;
                case FCNodeType.Assign:
                    Instance.view.Tab_Asg_LeftExp.Text = node.LeftExp;
                    Instance.view.Tab_Asg_RightExp.Text = node.RightExp;
                    break;
                case FCNodeType.IF:
                    Instance.view.Tab_IF_ConditionBox.Text = node.ConditionExp;
                    break;
                case FCNodeType.IO:
                    Instance.view.Tab_IO_Exp.Text = node.IOExp;
                    if (node.IsOutPut)
                    {
                        Instance.view.IsInput = !node.IsOutPut;
                    }
                    break;
                case FCNodeType.Label:
                    break;
                default:
                    break;
            }

        }

        static public void Tab_Common_TextInputed(object s, EventArgs e, Action<TextBox> check = null)
        {
            string t = (s as TextBox).Text;
            if (s == Instance.view.Tab_Common_Text1)
            {
                if (Instance.node.LogicRect.X == int.Parse(t))
                    return;
                Instance.node.LogicRect.X = int.Parse((s as TextBox).Text);
                Instance.changed?.Invoke(Instance.node, "rect");
            }
            else if (s == Instance.view.Tab_Common_Text2)
            {
                if (Instance.node.LogicRect.Y == int.Parse(t))
                    return;
                Instance.node.LogicRect.Y = int.Parse((s as TextBox).Text);
                Instance.changed?.Invoke(Instance.node, "rect");
            }
            else if (s == Instance.view.Tab_Common_Text3)
            {
                if (Instance.node.LogicRect.Width == int.Parse(t))
                    return;
                Instance.node.LogicRect.Width = int.Parse((s as TextBox).Text);
                Instance.changed?.Invoke(Instance.node, "rect");
            }
            else if (s == Instance.view.Tab_Common_Text4)
            {
                if (Instance.node.LogicRect.Height == int.Parse(t))
                    return;
                Instance.node.LogicRect.Height = int.Parse((s as TextBox).Text);
                Instance.changed?.Invoke(Instance.node, "rect");
            }
        }
    }
}
